using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;
using System.Text.RegularExpressions;
using System.Text;

namespace CMS.admin
{
    public partial class fileManagers : System.Web.UI.Page
    {
        //-- path to GIF icon image files (absolute)
        private string _strImagePath;
        //-- hide any files matching pattern
        private string _strHideFilePattern;
        //-- hide any folders matching pattern
        private string _strHideFolderPattern;
        //-- force user to stay on paths matching pattern
        private string _strAllowedPathPattern;
        //-- flush rows to the browser as they are written
        private bool _blnFlushContent;

        private const string _strRenameTag = "_2_";
        private const string _strCheckboxTag = "checked_";
        private const string _strActionTag = "action";
        private const string _strWebPathTag = "path";
        private const string _strColSortTag = "sort";

        private const string _strTargetFolderTag = "targetfolder";
        private Exception _FileOperationException;

        public string RenameTag
        {
            get { return _strRenameTag; }
        }

        /// <summary>
        /// tag used to indicate the action field in the form
        /// </summary>
        public string ActionTag
        {
            get { return _strActionTag; }
        }

        /// <summary>
        /// tag used to indicate file checkboxes in the form
        /// </summary>
        public string CheckboxTag
        {
            get { return _strCheckboxTag; }
        }

        /// <summary>
        /// tag used to indicate the target folder field in the form
        /// </summary>
        public string TargetFolderTag
        {
            get { return _strTargetFolderTag; }
        }

        /// <summary>
        /// returns the current web path being browsed
        /// </summary>
        public string CurrentWebPath
        {
            get { return WebPath(); }
        }

        /// <summary>
        /// returns the current script filename (.aspx)
        /// </summary>
        public string ScriptName
        {
            get { return Request.ServerVariables["script_name"].ToString(); }
        }

        /// <summary>
        /// This event fires when the page is being loaded
        /// </summary>
        private void Page_Load(System.Object sender, System.EventArgs e)
        {
            //-- get .config settings    
            _strHideFolderPattern = GetConfigString("HideFolderPattern");
            _strHideFilePattern = GetConfigString("HideFilePattern");
            _strAllowedPathPattern = GetConfigString("AllowedPathPattern");
            _strImagePath = GetConfigString("ImagePath", "../images/");
            _blnFlushContent = (!string.IsNullOrEmpty(GetConfigString("FlushContent")));

            HandleAction();
            WriteTable();
            UpUrl();
        }

        private string GetConfigString(string p)
        {
            return "";
            //throw new Exception("The method or operation is not implemented.");
        }

        private string GetConfigString(string strKey, string strDefaultValue)
        {
            if (strDefaultValue == null)
            {

                strDefaultValue = "";
            }
            strKey = "/" + strKey;
            if (ConfigurationSettings.AppSettings[strKey] == null)
            {
                return strDefaultValue;
            }
            else
            {
                return Convert.ToString(ConfigurationSettings.AppSettings[strKey]);
            }
        }

        /// <summary>
        /// performs the user action indicated in the hidden Action form field
        /// </summary>
        public void HandleAction()
        {


            if (Request.Form[_strActionTag] == null)
                return;

            string strAction = Request.Form[_strActionTag].ToString().ToLower();
            if (string.IsNullOrEmpty(strAction))
                return;

            switch (strAction)
            {
                case "newfolder":
                    MakeFolder(folderName.Text);
                    break;
                case "upload":
                    SaveUploadedFile();
                    break;
                default:
                    ProcessCheckedFiles(strAction);
                    break;
            }
            if ((_FileOperationException != null))
            {
                WriteError(_FileOperationException);
            }
        }

        /// <summary>
        /// performs the specified action on all checked files
        /// </summary>
        private void ProcessCheckedFiles(string strAction)
        {
            string strName = null;
            int intTagLength = _strCheckboxTag.Length;
            ArrayList FileList = new ArrayList();
            foreach (GridViewRow row in GridView1.Rows)
            {
                CheckBox ck = (CheckBox)row.FindControl("checked_");
                HiddenField fileName = (HiddenField)row.FindControl("fileName");
                if (ck.Checked)
                {
                    _FileOperationException = null;
                    strName = fileName.Value;
                    FileList.Add(strName);
                    switch (strAction)
                    {
                        case "delete":
                            DeleteFileOrFolder(strName);
                            break;
                        case "move":
                            MakeFolder(folderName.Text);
                            MoveFileOrFolder(strName);
                            break;
                        case "copy":
                            MakeFolder(folderName.Text);
                            CopyFileOrFolder(strName);
                            break;
                        case "rename":
                            RenameFileOrFolder(strName, newName.Value);
                            break;
                    }
                }
            }

            //-- certain operations must work on all the selected files/folders at once.
            if (strAction == "zip")
            {
                ZipFileOrFolder(FileList);
            }
        }

        /// <summary>
        /// Saves the first HttpPostedFile (if there is one) to the current folder
        /// </summary>
        private void SaveUploadedFile()
        {
            if (Request.Files.Count > 0)
            {
                HttpPostedFile pf = Request.Files.Get(0);
                if (pf.ContentLength > 0)
                {
                    string strFilename = pf.FileName;
                    string strTargetFile = GetLocalPath(Path.GetFileName(strFilename));
                    //-- make sure we clear out any existing file before uploading
                    if (File.Exists(strTargetFile))
                    {
                        DeleteFileOrFolder(strFilename);
                    }
                    try
                    {
                        pf.SaveAs(strTargetFile);
                    }
                    catch (Exception ex)
                    {
                        _FileOperationException = ex;
                    }
                }
            }
        }

        public void WriteTable()
        {
            int intRowsRendered = 0;
            {
                intRowsRendered = WriteRows();
                if (intRowsRendered < 0)
                    return;
            }
        }

        public int WriteRows()
        {
            const string strPathError = "The path '{0}' {1} <a href='javascript:history.go(-1);'>Go back</a>";

            //-- make sure we're allowed to look at this web path
            if (!string.IsNullOrEmpty(_strAllowedPathPattern) && !System.Text.RegularExpressions.Regex.IsMatch(WebPath(), _strAllowedPathPattern))
            {
                WriteErrorRow(string.Format(strPathError, WebPath(), "is not allowed because it does not match the pattern '" + Server.HtmlEncode(_strAllowedPathPattern) + "'."));
                return -1;
            }

            //-- make sure this directory exists on the server
            string strLocalPath = GetLocalPath("");
            if (!Directory.Exists(strLocalPath))
            {
                WriteErrorRow(string.Format(strPathError, WebPath(), "does not exist."));
                return -1;
            }

            //-- make sure we can get the files and directories for this directory
            DirectoryInfo[] da = null;
            FileInfo[] fa = null;
            try
            {
                DirectoryInfo di = new DirectoryInfo(strLocalPath);
                da = di.GetDirectories();
                fa = di.GetFiles();
            }
            catch (Exception ex)
            {
                WriteErrorRow(ex);
                return -1;
            }

            DataTable dt = new DataTable();
            {
                dt.Columns.Add(new DataColumn("Name", typeof(System.String)));
                dt.Columns.Add(new DataColumn("IsFolder", typeof(System.Boolean)));
                dt.Columns.Add(new DataColumn("FileExtension", typeof(System.String)));
                dt.Columns.Add(new DataColumn("Attr", typeof(System.String)));
                dt.Columns.Add(new DataColumn("Size", typeof(System.Int64)));
                dt.Columns.Add(new DataColumn("strFileLink", typeof(System.String)));
                dt.Columns.Add(new DataColumn("fileIconLookup", typeof(System.String)));
            }
            dt.BeginLoadData();
            foreach (DirectoryInfo d in da)
            {
                AddRowToFileInfoTable(d, dt);
            }
            foreach (FileInfo f in fa)
            {
                AddRowToFileInfoTable(f, dt);
            }
            dt.EndLoadData();
            dt.AcceptChanges();

            if (dt.Rows.Count == 0)
            {
                //WriteErrorRow("(no files)");
                return 0;
            }

            //-- sort and render intermediate DataView from our DataTable
            DataView dv = null;
            if (string.IsNullOrEmpty(SortColumn()))
            {
                dv = dt.DefaultView;
            }
            else
            {
                dv = new DataView(dt);
                GridView1.DataSource = dt;
                GridView1.DataBind();

                if (SortColumn().StartsWith("-"))
                {
                    dv.Sort = "IsFolder, " + SortColumn().Substring(1) + " desc";
                }
                else
                {
                    dv.Sort = "IsFolder desc, " + SortColumn();
                }
            }

            int intRenderedRows = 0;

            return intRenderedRows;
        }

        /// <summary>
        /// returns intermediate DataTable of File/Directory info 
        /// to be used for sorting prior to display
        /// </summary>
        private DataTable GetFileInfoTable()
        {
            DataTable dt = new DataTable();
            {
                dt.Columns.Add(new DataColumn("Name", typeof(System.String)));
                dt.Columns.Add(new DataColumn("IsFolder", typeof(System.Boolean)));
                dt.Columns.Add(new DataColumn("FileExtension", typeof(System.String)));
                dt.Columns.Add(new DataColumn("Attr", typeof(System.String)));
                dt.Columns.Add(new DataColumn("Size", typeof(System.Int64)));

            }
            //.Add(New DataColumn("Modified", GetType(System.DateTime)))
            //.Add(New DataColumn("Created", GetType(System.DateTime)))
            return dt;
        }

        /// <summary>
        /// translates a FileSystemInfo entry to a DataRow in our intermediate DataTable
        /// </summary>
        private void AddRowToFileInfoTable(FileSystemInfo fi, DataTable dt)
        {
            DataRow dr = dt.NewRow();
            string fileIconLookup = null;
            string Attr = AttribString(fi.Attributes);
            {
                dr["Name"] = fi.Name;
                dr["FileExtension"] = Path.GetExtension(fi.Name);
                dr["Attr"] = Attr;
                if (Attr.IndexOf("d") > -1)
                {
                    dr["IsFolder"] = true;
                    dr["Size"] = 0;
                }
                else
                {
                    dr["IsFolder"] = false;
                    long t = new FileInfo(fi.FullName).Length;
                    dr["Size"] = FormatKB(t);// new FileInfo(fi.FullName).Length;
                }


                string strFileLink = null;
                string strFileName = Convert.ToString(fi.Name);
                string strFilePath = WebPathCombine(WebPath(), strFileName);

                bool blnFolder = IsDirectory(fi.Name);

                if (Attr.IndexOf("d") > -1)
                {
                    if (!string.IsNullOrEmpty(_strHideFolderPattern) && Regex.IsMatch(strFileName, _strHideFolderPattern, RegexOptions.IgnoreCase))
                    {
                        return;
                    }
                    strFileLink = PageUrl(strFilePath, "").ToString() + strFileName + "</A>";
                }
                else
                {
                    if (!string.IsNullOrEmpty(_strHideFilePattern) && Regex.IsMatch(strFileName, _strHideFilePattern, RegexOptions.IgnoreCase))
                    {
                        return;
                    }
                    strFileLink = "<A href=\"" + strFilePath + "\" target=\"_blank\">" + strFileName + "</A>";
                }
                dr["strFileLink"] = strFileLink;
                fileIconLookup = FileIconLookup(dr, Attr);
                dr["fileIconLookup"] = fileIconLookup;
            }
            //.Item("Modified") = fi.LastWriteTime
            //.Item("Created") = fi.CreationTime
            dt.Rows.Add(dr);
        }

        private string SortColumn()
        {
            if (Request.QueryString[_strColSortTag] == null)
            {
                return "Name";
            }
            else
            {
                return Request.QueryString[_strColSortTag];
            }
        }

        /// <summary>
        /// Returns the current URL path we're browsing at the moment
        /// </summary>
        public string WebPath()
        {
            string strPath = Request.QueryString[_strWebPathTag];
            if (strPath == null || string.IsNullOrEmpty(strPath))
            {
                strPath = GetConfigString("DefaultPath", "~/Uploads/");
            }
            return strPath;
        }

        /// <summary>
        /// Returns the URL for one level "up" from our current WebPath()
        /// </summary>
        private string UpUrl()
        {
            string strUp = Regex.Replace(WebPath(), "/[^/]+$", "");
            if (string.IsNullOrEmpty(strUp) | strUp == "/")
            {
                strUp = GetConfigString("DefaultPath", "~/Uploads/");
            }
            return PageUrl(strUp, "");
        }

        /// <summary>
        /// return partial URL to this page, optionally specifying a new target path
        /// </summary>

        private string PageUrl(string NewPath, string NewSortColumn)
        {
            bool blnSortProvided = (!string.IsNullOrEmpty(NewSortColumn));

            //-- if not provided, use the current values in the querystring
            if (string.IsNullOrEmpty(NewPath))
                NewPath = WebPath();
            if (string.IsNullOrEmpty(NewSortColumn))
                NewSortColumn = SortColumn();
            StringBuilder sHref = new StringBuilder();
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            {
                sb.Append("<A href=\"");
                sb.Append(ScriptName);
                sHref.Append(ScriptName);
                sb.Append("?");
                sHref.Append("?");
                sb.Append(_strWebPathTag);
                sHref.Append(_strWebPathTag);
                sb.Append("=");
                sHref.Append("=");
                sb.Append(NewPath);
                sHref.Append(NewPath);
                if (!string.IsNullOrEmpty(NewSortColumn))
                {
                    sb.Append("&");
                    sHref.Append("&");
                    sb.Append(_strColSortTag);
                    sHref.Append(_strColSortTag);
                    sb.Append("=");
                    sHref.Append("=");
                    if (blnSortProvided & (NewSortColumn.ToLower() == SortColumn().ToLower()))
                    {
                        sb.Append("-");
                        sHref.Append("-");
                    }
                    sb.Append(NewSortColumn);
                    sHref.Append(NewSortColumn);
                }
                sb.Append("\">");
            }
            up.HRef = sHref.ToString();
            return sb.ToString();
        }

        /// <summary>
        /// given file object, return formatted KB size in text
        /// </summary>
        private string FormatKB(long FileLength)
        {
            return string.Format("{0:N0}", (FileLength / 1024));
        }

        /// <summary>
        /// turn numeric attribute into standard "RHSDAC" text
        /// </summary>
        private string AttribString(System.IO.FileAttributes a)
        {
            StringBuilder sb = new StringBuilder();
            if ((a & FileAttributes.ReadOnly) > 0)
                sb.Append("ReadOnly");
            if ((a & FileAttributes.Hidden) > 0)
                sb.Append("h");
            if ((a & FileAttributes.System) > 0)
                sb.Append("s");
            if ((a & FileAttributes.Directory) > 0)
                sb.Append("d");
            if ((a & FileAttributes.Archive) > 0)
                sb.Append("a");
            if ((a & FileAttributes.Compressed) > 0)
                sb.Append("c");
            return sb.ToString();
        }

        /// <summary>
        /// path.combine works great, but is filesystem-centric; we just convert the slashes
        /// </summary>
        private string WebPathCombine(string path1, string path2)
        {
            string strTemp = Path.Combine(path1, path2).Replace("\\", "/");
            if (strTemp.IndexOf("~/") > -1)
            {
                strTemp = strTemp.Replace("~/", Page.ResolveUrl("~/"));
            }
            return strTemp;
        }

        /// <summary>
        /// given filename, return URL to icon image for that filetype
        /// </summary>

        //private string FileIconLookup(DataRowView drv)
        private string FileIconLookup(DataRow dr, string attr)
        {
            //if (IsDirectory(dr))
            if (attr.IndexOf("d") > -1)
            {
                return WebPathCombine(_strImagePath, "file/folder.gif");
            }

            switch (Convert.ToString(dr["FileExtension"]))
            {
                case ".gif":
                case ".peg":
                case ".jpe":
                case ".jpg":
                case ".png":
                    return WebPathCombine(WebPath(), Convert.ToString(dr["Name"]));
                //Return "file_image.gif"
                case ".txt":
                    return WebPathCombine(_strImagePath, "file/text.gif");
                case ".htm":
                case ".xml":
                case ".xsl":
                case ".css":
                case ".html":
                case ".config":
                    return WebPathCombine(_strImagePath, "file/html.gif");
                case ".mp3":
                case ".wav":
                case ".wma":
                case ".au":
                case ".mid":
                case ".ram":
                case ".rm":
                case ".snd":
                case ".asf":
                    return WebPathCombine(_strImagePath, "file/audio.gif");
                case ".zip":
                case "tar":
                case ".gz":
                case ".rar":
                case ".cab":
                case ".tgz":
                    return WebPathCombine(_strImagePath, "file/compressed.gif");
                case ".asp":
                case ".wsh":
                case ".js":
                case ".vbs":
                case ".aspx":
                case ".cs":
                case ".vb":
                    return WebPathCombine(_strImagePath, "file/script.gif");
                default:
                    return WebPathCombine(_strImagePath, "file/generic.gif");
            }
        }

        /// <summary>
        /// writes a table row containing information about the file or folder
        /// </summary>

        /// <summary>
        /// optionally dumps the current response buffer to the client as it is being rendered.
        /// This is faster, but it can cause problems with some HTTP filters 
        /// so it is off by default.
        /// </summary>
        private void Flush()
        {
            if (_blnFlushContent)
                Response.Flush();
        }

        private string GetLocalPath(string strFilename)
        {
            return Path.Combine(Server.MapPath(WebPath()), strFilename);
        }

        /// <summary>
        /// converts a filesystem path to a relative path based on our current 
        /// file browsing path, WITHOUT a leading slash
        /// </summary>
        private string MakeRelativePath(string strFilename)
        {
            string strRelativePath = strFilename.Replace(Server.MapPath(WebPath()).ToString(), "");
            if (strRelativePath.StartsWith("\\"))
            {
                return strRelativePath.Substring(1);
            }
            else
            {
                return strRelativePath;
            }
        }

        /// <summary>
        /// maps the current web path, plus target folder, to a server filesystem path
        /// </summary>
        private string GetTargetPath(string strFilename)
        {
            if (strFilename == null)
            {
                strFilename = "";
            }
            //            return Path.Combine(Path.Combine(GetLocalPath(""), Request.Form[_strTargetFolderTag]), strFilename);
            return Path.Combine(Path.Combine(GetLocalPath(""), folderName.Text), strFilename);
        }

        /// <summary>
        /// returns True if the provided path is an existing directory
        /// </summary>
        private bool IsDirectory(string strFilepath)
        {
            return Directory.Exists(strFilepath);
        }

        /// <summary>
        /// Returns true if this DataRowView represents a directory/folder
        /// </summary>
        private bool IsDirectory(DataRowView drv)
        {
            return Convert.ToString(drv["attr"]).IndexOf("d") > -1;
        }

        /// <summary>
        /// deletes a file or folder
        /// </summary>
        private void DeleteFileOrFolder(string strName)
        {
            string strLocalPath = GetLocalPath(strName);
            try
            {
                RemoveReadOnly(strLocalPath);
                if (IsDirectory(strLocalPath))
                {
                    Directory.Delete(strLocalPath, true);
                }
                else
                {
                    File.Delete(strLocalPath);
                }
            }
            catch (Exception ex)
            {
                _FileOperationException = ex;
            }
        }

        /// <summary>
        /// moves a file from the current folder to the target folder
        /// </summary>
        private void MoveFileOrFolder(string strName)
        {
            string strLocalPath = GetLocalPath(strName);
            string strTargetPath = GetTargetPath(strName);
            try
            {
                if (IsDirectory(strLocalPath))
                {
                    Directory.Move(strLocalPath, strTargetPath);
                }
                else
                {
                    File.Move(strLocalPath, strTargetPath);
                }
            }
            catch (Exception ex)
            {
                _FileOperationException = ex;
            }
        }

        /// <summary>
        /// moves a file from the current folder to the target folder
        /// </summary>
        private void CopyFileOrFolder(string strName)
        {
            string strLocalPath = GetLocalPath(strName);
            string strTargetPath = GetTargetPath(strName);// (strName);

            try
            {
                if (IsDirectory(strLocalPath))
                {
                    CopyFolder(strLocalPath, strTargetPath, true);
                }
                else
                {
                    File.Copy(strLocalPath, strTargetPath);
                }
            }
            catch (Exception ex)
            {
                _FileOperationException = ex;
            }
        }

        /// <summary>
        /// Compress all the selected files
        /// due to limitations of SharpZipLib, this must be done in one pass 
        /// (it cannot modify an existing zip file!)
        /// </summary>
        private void ZipFileOrFolder(ArrayList FileList)
        {
            string ZipTargetFile = null;

            if (FileList.Count == 1)
            {
                ZipTargetFile = GetLocalPath(Path.ChangeExtension(Convert.ToString(FileList[0]), ".zip"));
            }
            else
            {
                ZipTargetFile = GetLocalPath("ZipFile.zip");
            }

            FileStream zfs = default(FileStream);
            ICSharpCode.SharpZipLib.Zip.ZipOutputStream zs = default(ICSharpCode.SharpZipLib.Zip.ZipOutputStream);
            try
            {
                if (File.Exists(ZipTargetFile))
                {
                    zfs = File.OpenWrite(ZipTargetFile);
                }
                else
                {
                    zfs = File.Create(ZipTargetFile);
                }

                zs = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(zfs);

                ExpandFileList(FileList);

                foreach (string strName in FileList)
                {
                    ICSharpCode.SharpZipLib.Zip.ZipEntry ze = default(ICSharpCode.SharpZipLib.Zip.ZipEntry);
                    //-- the ZipEntry requires a preceding slash if the file is a folder
                    if (strName.IndexOf("\\") > -1 & !strName.StartsWith("\\"))
                    {
                        ze = new ICSharpCode.SharpZipLib.Zip.ZipEntry("\\" + strName);
                    }
                    else
                    {
                        ze = new ICSharpCode.SharpZipLib.Zip.ZipEntry(strName);
                    }

                    ze.DateTime = DateTime.Now;
                    zs.PutNextEntry(ze);

                    FileStream fs = default(FileStream);
                    try
                    {
                        fs = File.OpenRead(GetLocalPath(strName));
                        byte[] buffer = new byte[2049];
                        int len = fs.Read(buffer, 0, buffer.Length);
                        while (len > 0)
                        {
                            zs.Write(buffer, 0, len);
                            len = fs.Read(buffer, 0, buffer.Length);
                        }
                    }
                    catch (Exception ex)
                    {
                        _FileOperationException = ex;
                    }
                    finally
                    {
                        if ((fs != null))
                            fs.Close();
                        zs.CloseEntry();
                    }
                }
            }
            finally
            {
                if ((zs != null))
                    zs.Close();
                if ((zfs != null))
                    zfs.Close();
            }
        }

        /// <summary>
        /// renames a file; assumes filename is "(oldname)(renametag)(newname)"
        /// </summary>
        private void RenameFileOrFolder(string strName, string nName)
        {
            string strOldName = null;
            string strNewName = null;
            //int intTagLoc = strName.IndexOf(_strRenameTag);
            //if (intTagLoc == -1)
            //return;

            strOldName = strName;// strName.Substring(0, intTagLoc);
            strNewName = nName;// strName.Substring(intTagLoc + _strRenameTag.Length);
            if (strOldName == strNewName)
                return;

            string strOldPath = GetLocalPath(strOldName);
            string strNewPath = GetLocalPath(strNewName);

            try
            {
                if (IsDirectory(strOldPath))
                {
                    Directory.Move(strOldPath, strNewPath);
                }
                else
                {
                    File.Move(strOldPath, strNewPath);
                }
            }
            catch (Exception ex)
            {
                _FileOperationException = ex;
            }
        }

        /// <summary>
        /// creates a subfolder in the current folder
        /// </summary>
        private void MakeFolder(string strFilename)
        {
            string strLocalPath = GetLocalPath(strFilename);
            //string strLocalPath = GetLocalPath("tungPM123");
            try
            {
                if (!Directory.Exists(strLocalPath))
                {
                    Console.WriteLine("1234567890876543");
                    Directory.CreateDirectory(strLocalPath);
                }
            }
            catch (Exception ex)
            {
                _FileOperationException = ex;
            }
        }

        private void CopyFolder(string strSourceFolderPath, string strDestinationFolderPath, bool blnOverwrite)
        {
            //-- make sure target folder exists
            if (!Directory.Exists(strDestinationFolderPath))
            {
                Directory.CreateDirectory(strDestinationFolderPath);
            }

            //-- copy all of the files in this folder to the destination folder
            foreach (string strFilePath in Directory.GetFiles(strSourceFolderPath))
            {
                string strFileName = Path.GetFileName(strFilePath);
                //-- if exception, will be caught in calling proc
                File.Copy(strFilePath, Path.Combine(strDestinationFolderPath, strFileName), blnOverwrite);
            }

            //-- copy all of the subfolders in this folder
            foreach (string strFolderPath in Directory.GetDirectories(strSourceFolderPath))
            {
                string strFolderName = Regex.Match(strFolderPath, "[^\\\\]+$").ToString();
                CopyFolder(strFolderPath, Path.Combine(strDestinationFolderPath, strFolderName), blnOverwrite);
            }
        }

        /// <summary>
        /// Given an ArrayList of file and folder names, ensure that the 
        /// ArrayList contains all subfolder file names
        /// </summary>

        private void ExpandFileList(ArrayList FileList)
        {
            string strLocalPath = null;
            ArrayList NewFileList = new ArrayList();

            for (int i = FileList.Count - 1; i >= 0; i += -1)
            {
                strLocalPath = GetLocalPath(Convert.ToString(FileList[i]));
                if (IsDirectory(strLocalPath))
                {
                    FileList.Remove(FileList[i]);
                    AddFilesFromFolder(strLocalPath, ref NewFileList);
                }
            }

            if (NewFileList.Count > 0)
            {
                FileList.AddRange(NewFileList);
            }
        }

        /// <summary>
        /// Adds all the files in the specified folder to the FileList, 
        /// </summary>
        private void AddFilesFromFolder(string strFolderName, ref ArrayList FileList)
        {
            if (!Directory.Exists(strFolderName))
                return;

            try
            {
                foreach (string strName in Directory.GetFiles(strFolderName))
                {
                    FileList.Add(MakeRelativePath(strName));
                }
            }
            catch (Exception ex)
            {
                //-- mostly to catch "access denied"
                _FileOperationException = ex;
            }

            try
            {
                foreach (string strName in Directory.GetDirectories(strFolderName))
                {
                    AddFilesFromFolder(strName, ref FileList);
                }
            }
            catch (Exception ex)
            {
                //-- mostly to catch "access denied"
                _FileOperationException = ex;
            }
        }

        /// <summary>
        /// recursively removes the read only tag from a file or folder, if it is present
        /// </summary>
        private void RemoveReadOnly(string strPath)
        {
            if (IsDirectory(strPath))
            {
                foreach (string strFile in Directory.GetFiles(strPath))
                {
                    RemoveReadOnly(strFile);
                }
                foreach (string strFolder in Directory.GetDirectories(strPath))
                {
                    RemoveReadOnly(strFolder);
                }
            }
            else
            {
                FileInfo fi = new FileInfo(strPath);
                if ((fi.Attributes & FileAttributes.ReadOnly) != 0)
                {
                    fi.Attributes = fi.Attributes ^ FileAttributes.ReadOnly;
                }
            }
        }

        /// <summary>
        /// returns the windows identity that ASP.NET is currently running under
        /// </summary>
        private string CurrentIdentity()
        {
            return System.Security.Principal.WindowsIdentity.GetCurrent().Name;
        }

        /// <summary>
        /// adds additional helpful information to certain types of exceptions
        /// </summary>
        private string GetFriendlyErrorMessage(Exception ex)
        {
            string strMessage = ex.Message;
            if (ex is System.UnauthorizedAccessException)
            {
                strMessage += " The account '" + CurrentIdentity() + "' may not have permission to this file or folder.";
            }
            return strMessage;
        }

        /// <summary>
        /// Parse and display any exceptions encountered during a file operation
        /// </summary>
        private void WriteError(Exception ex)
        {
            WriteError(GetFriendlyErrorMessage(ex));
        }
        private void WriteError(string strText)
        {
            Response.Write("<DIV class=\"Error\">");
            Response.Write(strText);
            Response.Write("</DIV>");
        }
        private void WriteErrorRow(Exception ex)
        {
            WriteErrorRow(GetFriendlyErrorMessage(ex));
        }
        private void WriteErrorRow(string strText)
        {
            Response.Write("<TR><TD><TD><TD colspan=5><DIV class=\"Error\">");
            Response.Write(strText);
            Response.Write("</DIV>");
        }

        /// <summary>
        /// Paging Gridview
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void GridView1_PageIndexChanging(Object sender, GridViewPageEventArgs e)
        {
            GridView1.PageIndex = e.NewPageIndex;
            WriteRows();
        }

    }
}
